package tool.soft

import akka.stream.Materializer

import java.io.File
import command.CommandExec
import dao._
import models.Tables
import org.joda.time.DateTime
import play.api.mvc.{AnyContent, Request}
import play.twirl.api.Html
import shared.Pojo._
import tool.Pojo._
import tool._
import tool.plot._
import tool.soft.AllSoft.SoftBT

import scala.collection.immutable.SeqMap
import implicits.Implicits._
import models.Tables._
import play.api.data.FormBinding
import tool.softT.{AllSoftBT, DiffAnaSoftBT}
import play.api.i18n.Messages
import play.api.libs.ws.WSClient
import utils.Utils
import upickle.default._

/**
 * Created by yz on 15/9/2020
 */
object LimmaAnaSoft extends SoftBT with LimmaAnaSoftT {

  override def getResultFileName: String = {
    "Diff_Metabolite.csv"
  }

  override def getFileInfos(workspaceDir: File, index: Int)(implicit matrixFileDataDao: MatrixFileDataDao, messages: Messages): List[FileInfoData] = {
    workspaceDir.myListFiles.filter { x =>
      x.isDirectory
    }.map { x =>
      val name = x.getName
      FileInfoData("res.csv", messages("limmaResult", name), fileRelPath = name)
    }
  }

  override def getResultHtml(missionId: Int)(implicit request: Request[AnyContent], messages: Messages): Html = {
    views.html.user.mission.limmaAnaResult(missionId)
  }

  override def produceConfigFile(workspaceDir: File, index: Int)(implicit request: Request[AnyContent],
                                                                 formBinding: FormBinding) = {
    data.lines().toTxtFile(Tool.getCalculateConfigTxtFile(workspaceDir))
    Utils.t2ConfigFile(workspaceDir, data)
  }

  def getArg(implicit request: Request[AnyContent], messages: Messages, formBinding: FormBinding): ujson.Value = {
    val replaceArg = data.fillMethod match {
      case "knn" => SeqMap(messages("missingValueImputation") -> messages("kNNImputation"), messages("knnKValue") -> data.knn)
      case "modeFill" => SeqMap(messages("missingValueImputation") -> messages("modeFill"))
      case "fillWithMedian" => SeqMap(messages("missingValueImputation") -> messages("fillWithMedian"))
      case "delete" => SeqMap(messages("missingValueImputation") -> messages("delete"))
    }
    val argMap = SeqMap(messages("groups") -> data.groups.mkString(";"),
      messages("covariate") -> data.covs.mkString(";"), messages("variableType") -> data.kinds.mkString(";")) ++
      replaceArg
    writeJs(argMap)
  }

  override def getHtml(missionName: String, missionId: Option[Int])(implicit request: Request[AnyContent], messages: Messages): Html = {
    views.html.user.soft.limmaAna(missionName, missionId)
  }

  override def getMission(implicit request: Request[AnyContent], matrixFileDataDao: MatrixFileDataDao,
                          messages: Messages, formBinding: FormBinding): Tables.MissionRow = {
    val input = List(data.file, data.groupFile)
    val argJson = getArg
    MissionRow(id = 0, missionName = s"${data.missionName}", kind = nameStr, userId = userId,
      startTime = new DateTime(), state = "preparing", arg = argJson, input = input)
  }

  override def produceInputFile(workspaceDir: File)(implicit request: Request[AnyContent], dao: MyDao,
                                                    formBinding: FormBinding): Any = {
    val rawDataFile = new File(workspaceDir, "AllMet_Raw.txt")
    Tool.produceRawDataFile(userId, data.file, rawDataFile)

    val groupFile = Tool.getGroupFile(workspaceDir)
    Tool.produceRawGroupFile(userId, data.groupFile, groupFile)
  }

  override def data(implicit request: Request[AnyContent], formBinding: FormBinding) = {
    FormTool.limmaAnaForm.bindFromRequest().get
  }

  override def resultDeal(workspaceDir: File, resultDir: File)(implicit ws: WSClient, materializer: Materializer): Unit = {
    super.resultDeal(workspaceDir, resultDir)
    workspaceDir.myListFiles.filter(_.isDirectory).foreach(_.dirCopyToDir(resultDir, Tool.fileNameFilter))
  }

  override def getCommandData(workspaceDir: File, resultDir: File, index: Int): List[CommandData] = {
    val command =
      s"""
         |${"Rscript".condaPath()} ${new File(Tool.rPath, "limma.R").unixPath}
           """.stripMargin
    List(CommandData(workspaceDir, List(command)))
  }

}

